#include "GrayscaleReconstruct.h"
#include "MorphologyOpen.h"
#include "MorphologyClose.h"
#include "MorphologyDilation.h"
#include "MorphologyErosion.h"



GrayscaleReconstruct::GrayscaleReconstruct (Core< int > se) : _se (se), 
		_type (OBR)
{

}



Ptr< QImage > GrayscaleReconstruct::process (Ptr< QImage > pSrcImage)
{
	Ptr< QImage > pTempImage;
	if (_type == OBR)
		return doOBR (pSrcImage);
	if (_type == CBR)
		return doCBR (pSrcImage);
	return NULL;
}

void GrayscaleReconstruct::setType (Type t)
{
	_type = t;
}

GrayscaleReconstruct::Type GrayscaleReconstruct::getType () const
{
	return _type;
}

Ptr< QImage > GrayscaleReconstruct::doOBR (Ptr< QImage > pSrcImage)
{
	Ptr< QImage > pTempImage;
	pTempImage = MorphologyOpen (_se).operate (pSrcImage);
	Ptr< QImage > pLastTempImage = pTempImage;
	Core< int > dilationCore (QSize (3, 3));
	MorphologyDilation dilationMethod (dilationCore);

	while (true) {
		pTempImage = dilationMethod.operate (pTempImage);
		// mask
		for (int v = 0; v < pSrcImage->height (); ++v)
		{
			QRgb * tempLine = (QRgb *)pTempImage->scanLine (v);
			QRgb * srcLine = (QRgb *)pSrcImage->scanLine (v);
			for (int u = 0; u < pSrcImage->width (); ++u) {
				int r = (qRed (tempLine[u]) > qRed (srcLine[u]) ? 
					qRed (srcLine[u]) : qRed (tempLine[u]));
				int g = (qGreen (tempLine[u]) > qGreen (srcLine[u]) ? 
					qGreen (srcLine[u]) : qGreen (tempLine[u]));
				int b = (qBlue (tempLine[u]) > qBlue (srcLine[u]) ? 
					qBlue (srcLine[u]) : qBlue (tempLine[u]));
				int a = qAlpha (tempLine[u]);
				tempLine[u] = qRgba (r, g, b, a);
			}
		}

		// compare
		bool isSame = true;
		for (int v = 0; v < pSrcImage->height (); ++v)
		{
			QRgb * tempLine = (QRgb *)pTempImage->scanLine (v);
			QRgb * lastLine = (QRgb *)pLastTempImage->scanLine (v);
			for (int u = 0; u < pSrcImage->width (); ++u) {
				if (tempLine[u] != lastLine[u])
					isSame = false;
			}
		}

		if (isSame)
			return pTempImage;

		pLastTempImage = pTempImage;
	}

}

Ptr< QImage > GrayscaleReconstruct::doCBR (Ptr< QImage > pSrcImage)
{
	Ptr< QImage > pTempImage;
	pTempImage = MorphologyClose (_se).operate (pSrcImage);
	Ptr< QImage > pLastTempImage = pTempImage;
	Core< int > dilationCore (QSize (3, 3));
	MorphologyErosion erosionMethod (dilationCore);

	while (true) {
		pTempImage = erosionMethod.operate (pTempImage);
		// mask
		for (int v = 0; v < pSrcImage->height (); ++v)
		{
			QRgb * tempLine = (QRgb *)pTempImage->scanLine (v);
			QRgb * srcLine = (QRgb *)pSrcImage->scanLine (v);
			for (int u = 0; u < pSrcImage->width (); ++u) {
				int r = (qRed (tempLine[u]) < qRed (srcLine[u]) ? 
					qRed (srcLine[u]) : qRed (tempLine[u]));
				int g = (qGreen (tempLine[u]) < qGreen (srcLine[u]) ? 
					qGreen (srcLine[u]) : qGreen (tempLine[u]));
				int b = (qBlue (tempLine[u]) < qBlue (srcLine[u]) ? 
					qBlue (srcLine[u]) : qBlue (tempLine[u]));
				int a = qAlpha (tempLine[u]);
				tempLine[u] = qRgba (r, g, b, a);
			}
		}

		// compare
		bool isSame = true;
		for (int v = 0; v < pSrcImage->height (); ++v)
		{
			QRgb * tempLine = (QRgb *)pTempImage->scanLine (v);
			QRgb * lastLine = (QRgb *)pLastTempImage->scanLine (v);
			for (int u = 0; u < pSrcImage->width (); ++u) {
				if (tempLine[u] != lastLine[u])
					isSame = false;
			}
		}

		if (isSame)
			return pTempImage;

		pLastTempImage = pTempImage;
	}

}
